CHAPTER 11

Arrays and Collections

Collection types have been around in various forms since the beginning of computer pro-gramming. The most basic type of collection is the array. This chapter will give a brief overview of arrays, but won’t go into much detail, as arrays have not changed much between .NET 1.1 and .NET 2.0. We’ll spend more time explaining the major generic collection interfaces and iterators, which are new to Visual Basic 2005 (VB 2005), along with the cool things you can do with them. Traditionally, creating enumerators for collection types has been mundane and annoying. Itera-tors make this task a breeze, while making your code a lot more readable in the process.

Introduction to Arrays

A VB array is a built-in, implicit type to the runtime. When you declare a type—whether it’s a class or structure—the runtime reserves the right to silently generate an array type based upon that new type. The array type that it generates is a reference type. The reference type that it generates is derived from System.Array, and ultimately from System.Object. Therefore, you can treat all arrays polymorphically through a reference to System.Array. That means that each array, no matter what concrete type of array it is, implements all of the methods and properties of System.Array.

You declare an array using parentheses following the type and not following the array variable name. The following example shows three ways to create an array of integers and print them to the console:

Imports System

Public Class EntryPoint
    Shared Sub Main()
        Dim array1 As Integer() = New Integer(10) {}
        Dim array2 As Integer() = New Integer() {2, 4, 6, 8}
        Dim array3 As Integer() = {1, 3, 5, 7}
        Dim i As Integer = 0

        For i = 0 To array1.Length - 1
            array1(i) = i * 2
        Next

        For Each item As Integer In array1
            Console.WriteLine("array1: " + item.ToString)
        Next

        Console.WriteLine(vbCrLf)

        For Each item As Integer In array2
            Console.WriteLine("array2: " + item.ToString)
        Next

        Console.WriteLine(vbCrLf)

        For Each item As Integer In array3
            Console.WriteLine("array3: " + item.ToString)
        Next
    End Sub
End Class

The longhand way to create an array instance and fill it with initial values is shown where array1 is initialized. In VB, an array’s lower bound is always 0 in order to meet the Common Language Specification (CLS) restriction that arrays have a 0 lower bound. The upper bound for array1is 10, as stated in the code, making for an array with 11 elements. Notice the use of the Newoperator to allocate the array1 and array2 instances on the heap. The omission of New to allocate the array3 instance is a notational shortcut.

One of the conveniences of .NET arrays is that they are range-checked. Therefore, if you step off the end of one of them, thus going out of bounds, the runtime will throw an IndexOutOfRangeException. Finally, notice that you can iterate through the elements in the array using a For Eachstatement. This works because System.Array implements IEnumerable. The section titled “IEnumerable(Of T), IEnumerator(Of T), IEnumerable, IEnumerator” describes IEnumerable and its cousin IEnumerator in more detail.

Type Convertibility and Covariance

When you declare an array to contain instances of a certain type, the instances that you may place in that array can actually be instances of a more derived type. For example, if you create an array that contains instances of type Animal, then you can feasibly insert an instance of Dog or Cat if both of them derive from Animal.

You can coerce array types in this other, even more interesting way:

Imports System

Public Class Animal
End Class

Public Class Dog
    Inherits Animal
End Class

Public Class Cat
    Inherits Animal
End Class

Public Class EntryPoint
    Shared Sub Main()
        Dim dogs As Dog() = New Dog(3) {}
        Dim cats As Cat() = New Cat(2) {}

        Dim animals As Animal() = dogs
        Dim moreAnimals As Animal() = cats
    End Sub
End Class

The assignment from dogs to animals and from cats to moreAnimals is something that you can do as long as their ranks match and the contained type is convertible from one to the other. Since both arrays in the previous example have a rank of 1, and Dog and Cat are type-convertible to Animal, the assignment works.

Note The full type information of an array comprises its rank (how many dimensions it has) and the type that it contains.

Array Covariance

An array element whose type is B may actually be of type A, provided that both A and Bare ref-erence types, and that B is a base type of Aor is implemented by A. This relationship is known as array covariance. Due to this covariance, all element assignments of reference type arrays are subject to a runtime type check to ensure that the value being assigned is an allowed type.